package controllers

import java.io.File
import dao._

import javax.inject.Inject
import play.api.libs.json.Json
import play.api.mvc._
import utils.Utils

import scala.concurrent.ExecutionContext.Implicits.global
import tool._
import models.Tables._
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import utils.Utils.{Info, Sender}

import scala.collection.mutable.ArrayBuffer
import scala.concurrent.Future
import implicits.Implicits._
import shared.Shared

/**
 * Created by yz on 2018/8/20
 */
class AdminController @Inject()(cc: ControllerComponents, formTool: FormTool,
                                tool: Tool, missionDao: MissionDao,
                                extraDataDao: ExtraDataDao, trashDao: TrashDao, pdfInfoDao: PdfInfoDao
                               )(
                                 implicit val accountDao: AccountDao,
                                 implicit val userDao: UserDao,
                                 implicit val userNameDao: UserNameDao,
                               ) extends AbstractController(cc) {

  def userManageBefore = Action { implicit request =>
    Ok(views.html.admin.userManage())
  }

  def logout = Action { implicit request =>
    Redirect(routes.AppController.loginBefore).flashing("info" -> "退出登录成功!", "class" -> Utils.successClass).
      removingFromSession(Shared.adminStr)
  }

  def changePasswordBefore = Action { implicit request =>
    Ok(views.html.admin.changePassword())
  }

  def getAllUser = Action.async { implicit request =>
    userDao.selectAll.map { x =>
      val array = Utils.getArrayByTs(x)
      Ok(Json.toJson(array))
    }
  }

  def userNameCheck = Action.async { implicit request =>
    val data = formTool.userNameForm.bindFromRequest.get
    userDao.selectByName(data.name).zip(accountDao.selectById1).map { case (optionUser, admin) =>
      optionUser match {
        case Some(y) => Ok(Json.obj("valid" -> false))
        case None =>
          val valid = if (data.name == admin.account) false else true
          Ok(Json.obj("valid" -> valid))
      }
    }
  }

  def deleteUserById = Action.async { implicit request =>
    val data = formTool.idForm.bindFromRequest().get
    userDao.deleteById(data.id).zip(pdfInfoDao.deleteById(data.id)).map { x =>
      Ok(Json.toJson("success"))
    }
  }

  def getUserById = Action.async { implicit request =>
    val data = formTool.idForm.bindFromRequest().get
    userDao.selectById(data.id).map { x =>
      Ok(Utils.getJsonByT(x))
    }
  }

  def updateUser = Action.async { implicit request =>
    val data = formTool.userForm.bindFromRequest().get
    userDao.update(data).map { x =>
      Ok(Json.toJson("success!"))
    }
  }

  def addUser = Action.async { implicit request =>
    val data = formTool.userForm.bindFromRequest().get
    val row = UserRow(0, data.name, data.password, new DateTime())
    userDao.insertAndReturning(row).flatMap { userId =>
      val pdfInfoRow = PdfInfoRow(userId, "深圳绘云医学检验实验室", "", "", "", "")
      val userNameRow = UserNameRow(userId, data.name)
      pdfInfoDao.insert(pdfInfoRow).zip(userNameDao.insert(userNameRow)).map { x =>
        Ok(Json.toJson("success!"))
      }
    }
  }

  def changePassword = Action.async { implicit request =>
    val data = formTool.changePasswordForm.bindFromRequest().get
    accountDao.selectById1.flatMap { x =>
      if (data.password == x.password) {
        accountDao.updatePassword(data.newPassword).map { y =>
          Redirect(routes.AppController.loginBefore).flashing("info" -> "密码修改成功!", "class" -> Utils.successClass).
            removingFromSession(Shared.adminStr)
        }
      } else {
        Future.successful(Redirect(routes.AdminController.changePasswordBefore).flashing("info" -> "密码错误!", "class" -> Utils.errorClass))
      }
    }
  }

  def deleteUserData = Action.async { implicit request =>
    val data = formTool.idForm.bindFromRequest().get
    userDao.deleteById(data.id).zip(pdfInfoDao.deleteById(data.id)).zip(extraDataDao.deleteByUserId(data.id)).
      zip(missionDao.deleteByUserId(data.id)).zip(trashDao.deleteByUserId(data.id)).zip(userNameDao.deleteById(data.id)).
      map { x =>
        val userDir = new File(Utils.userDir, s"${data.id}")
        Utils.deleteDirectory(userDir)
        Ok(Json.toJson("success"))
      }
  }

  def downloadDb = Action.async { implicit request =>
    missionDao.selectAll.zip(extraDataDao.selectAll).zip(userDao.selectAll).
      zip(trashDao.selectAll).zip(userNameDao.selectAll).map { case ((((missionRows, extraRows), users), trashs), userNames) =>
      val extraMap = extraRows.map(x => (x.id, x)).toMap
      val userMap = users.map(x => (x.id, x.name)).toMap
      val trashMap = trashs.map { x =>
        val isDelete = if (x.exist) "否" else "是"
        (x.id, isDelete)
      }.toMap
      val userNameMap = userNames.map(x => (x.userId, x.name)).toMap
      val headers = List("用户", "样品号", "姓名", "年龄", "AST", "ALT", "PLT", "Tyr", "TCA",
        "时间", "是否删除", "问诊记录",
        "送检单位", "地址", "性别", "送检科室", "申请医生", "门诊/住院号", "采样时间", "送检时间",
        "样本类型", "样本状态", "标题", "检验人", "审核人", "检验日期", "报告日期")
      val contents = missionRows.map { x =>
        val userName = userMap.getOrElse(x.userId, s"${userNameMap(x.userId)}(已删)")
        val isDelete = trashMap(x.id)
        val extra = extraMap.getOrElse(x.id, tool.getEmptyExtraDataRow(x.id, x.userId))
        List(userName, extra.sampleId, extra.name, x.age, x.ast, x.alt, x.plt, x.tyr, x.tca,
          x.endTime.toString, isDelete, extra.interviewRecord,
          extra.unit, extra.address, extra.sex, extra.office, extra.doctor, extra.number, extra.sampleTime,
          extra.submitTime,
          extra.sampleType, extra.sampleStatus, extra.title, extra.reporter, extra.checker, extra.submitTime,
          extra.reportDate)
      }.sortBy(_ (0))
      val lines = headers :: contents
      val tmpDir = tool.createTempDirectory("tmpDir")
      val file = new File(tmpDir, "用户记录.xlsx")
      lines.toXlsxFile(file)
      Ok.sendFile(file, onClose = () => {
        Utils.deleteDirectory(tmpDir)
      }).withHeaders(
        CONTENT_DISPOSITION -> Tool.getContentDisposition(s"${
          file.getName
        }"),
        CONTENT_TYPE -> "application/x-download"
      )

    }
  }

}
